home *** CD-ROM | disk | FTP | other *** search
Text File | 2001-01-26 | 69.7 KB | 2,044 lines |
- ## -*-Tcl-*- (nowrap)
- # ==========================================================================
- # Statistical Modes - an extension package for Alpha
- #
- # FILE: "stataMode.tcl"
- # created: 01/15/00 {07:15:32 pm}
- # last update: 01/26/01 {12:08:23 pm}
- # Description:
- #
- # For Stata "do" and output files.
- #
- # Author: Craig Barton Upright
- # E-mail: <cupright@princeton.edu>
- # mail: Princeton University, Department of Sociology
- # Princeton, New Jersey 08544
- # www: <http://www.princeton.edu/~cupright>
- #
- # Stata menu written, maintained by L. Phillip Schumm <pschumm@uchicago.edu>
- #
- # -------------------------------------------------------------------
- #
- # Copyright (c) 2000-2001 Craig Barton Upright, L. Phillip Schumm
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- #
- # ==========================================================================
- ##
-
- # ===========================================================================
- #
- # ◊◊◊◊ Initialization of Stta mode ◊◊◊◊ #
- #
-
- alpha::mode Stta 2.1.1 stataMenu {*.do *.ado} {
- stataMenu electricReturn electricSemicolon electricTab electricBraces
- } {
- # We require 7.4b21 for prefs handling.
- alpha::package require -loose AlphaTcl 7.4b21
- addMenu stataMenu "•155" Stta
- set unixMode(stata) {Stta}
- set modeCreator(S5x8) {Stta}
- } uninstall {
- catch {file delete [file join $HOME Tcl Modes stataMode.tcl]}
- catch {file delete [file join $HOME Tcl Completions SttaCompletions.tcl]}
- catch {file delete [file join $HOME Tcl Completions "Stta Tutorial.do"]}
- } help {
- file "Statistical Modes Help"
- } maintainer {
- "Craig Barton Upright" <cupright@princeton.edu>
- <http://www.princeton.edu/~cupright/>
- }
-
- hook::register quitHook Stta::quitHook
-
- proc stataMenu {} {}
-
- proc stataMode.tcl {} {}
-
- namespace eval Stta {}
-
- # ===========================================================================
- #
- # ◊◊◊◊ Stta mode variables ◊◊◊◊ #
- #
-
- # Removing obsolete preferences from earlier versions.
-
- set oldvars {
- abbrevColor addAbbreviations addArguments addFunctions addMacros
- addModifiers addParameters argumentColor codebookSuffix datedColor
- delimiter don'tRemindMe electricTab functionColor keywordColor
- localHelpOnly parameterColor macroColor modifierColor stataHelp
- }
-
- foreach oldvar $oldvars {prefs::removeObsolete SttamodeVars($oldvar)}
-
- unset oldvar oldvars
-
- # ===========================================================================
- #
- # Standard preferences recognized by various Alpha procs
- #
-
- newPref var fillColumn {75} Stta
- newPref var leftFillColumn {0} Stta
- newPref var prefixString {* } Stta
- newPref var wordBreak {[-a-zA-Z0-9\._\#]+} Stta
- newPref var wordBreakPreface {[^-a-zA-Z0-9\._\#]} Stta
- newPref flag wordWrap {0} Stta
-
- # ===========================================================================
- #
- # Flag preferences
- #
-
- newPref flag autoMark {0} Stta {Stta::rebuildMenu markStataFileAs}
-
- # Indent all continued commands, indicated by "/*" at the end of a command
- # line, or by the lack of a semi-colon if the "Semi Delimiter" preference
- # is set, by the full indentation amount rather than half.
- newPref flag fullIndent {1} Stta {Stta::rebuildMenu markStataFileAs}
-
- # Check this box if to use semicolons as a delimiter in do files. This
- # will be used in all electric completions.
- newPref flag semiDelimiter {0} Stta {Stta::rebuildMenu stataHelp}
-
- # By default command double-click will send a command to on-line help, and
- # option double-click sends a command to the local Stata application.
- # Check this box to switch these key combinations.
- newPref flag localHelp {0} Stta {Stta::rebuildMenu stataHelp}
-
- # Check this box if your keyboard does not have a "Help" key. This will
- # change some of the menu's key bindings.
- newPref flag noHelpKey {0} Stta {Stta::rebuildMenu stataHelp}
-
- # Set the list of flag preferences which can be changed in the menu.
-
- set SttaPrefsInMenu [list \
- "localHelp" \
- "noHelpKey" \
- "semiDelimiter" \
- "fullIndent" \
- ]
-
- # ===========================================================================
- #
- # Variable preferences
- #
-
- # Enter additional Stata commands or abbreviations to be colorized.
- newPref var addCommands {} Stta {Stta::colorizeStta}
-
- # Enter additional options or abbreviations to be colorized.
- newPref var addOptions {gen rep} Stta {Stta::colorizeStta}
-
- # Command double-clicking on a Stata keyword will send it to this url for a
- # help reference page.
- newPref url helpUrl {http://www.stata.com/help.cgi?} Stta
-
- # The "Stata Home Page" menu item will send this url to your browser.
- newPref url stataHomePage {http://www.stata.com/} Stta
-
- # Click on "Set" to find the local Stata application.
- newPref sig stataSig {S5x8} Stta
-
- # ===========================================================================
- #
- # Color preferences
- #
- # Nomenclature notes:
- #
- # Stata has five levels of processes.
- #
- # 1. "commands", "subcommands", "prefixes": describe, define, quietly,
- # 2. "parameters": textsize, maxobs, prefix, more,
- # 3. "functions": abs(), log(), sin(), ge, lt,
- # 4. "options": saving(), naxis graph, matrix graph,
- # 5. "modifiers": [weights= ], [frequency= ]
- #
- # and, just to help make sure that everything goes smoothly, we have
- #
- # 6. out of date (or "dated") commands: genrank, grebar
- #
- # For the most part, Stata is very good about not using the same name for a
- # command to refer to a function, parameter, or modifier. Options,
- # however, often have the same names as commands.
- #
- # The default setup of this mode is to colorize all of commands,
- # subcommands, prefixes, parameters, and macros blue. Options, functions,
- # modifiers, and symbols are colorized magenta. Dated commands are red.
- # The user does not have to specify all of these different levels -- only
- # Command, Comment, Option, String, and Symbol colors appear in the
- # preferences.
- #
- # In addition, non-ambiguous abbreviations of command names are allowed.
- # They could be entered as Additional Commands or Additional Options
- # through Config -- > Mode --> Mode Preferences.
- #
- # The sections which follow are based on release 3.1 of Stata, because that
- # was the latest full manual that I could get my hands on ...
- #
-
- # See the Statistical Modes Help file for an explanation of these different
- # categories, and lists of keywords.
- newPref color commandColor {blue} Stta {Stta::colorizeStta}
- newPref color commentColor {red} Stta {stringColorProc}
- newPref color optionColor {magenta} Stta {Stta::colorizeStta}
- newPref color stringColor {green} Stta {stringColorProc}
-
- # The color of symbols such as "+", "-", etc.
- newPref color symbolColor {magenta} Stta {Stta::colorizeStta}
-
- regModeKeywords -e {*} -b {/*} {*/} \
- -c $SttamodeVars(commentColor) \
- -s $SttamodeVars(stringColor) Stta {}
-
- # ==========================================================================
- #
- # Comment Character variables for Comment Line / Paragraph / Box menu items.
- #
-
- set Stta::commentCharacters(General) "* "
- set Stta::commentCharacters(Paragraph) [list "/* " " */" " * "]
- set Stta::commentCharacters(Box) [list "/*" 2 "*/" 2 "*" 3]
-
- # The Comment Line command is hard-wired -- except for the C and C++ modes,
- # if the commentCharacters(Paragraph) are different, then Comment Line will
- # automatically be bracketed. Thus I am simply redefining the command-d
- # key-binding to ignore commentLine
-
- Bind 'd' <c> {insertPrefix} Stta
-
- # ===========================================================================
- #
- # Flag Flip
- #
- # Called by menu items, change the value of flag preferences.
- #
-
- proc Stta::flagFlip {pref} {
-
- global mode SttamodeVars
-
- set SttamodeVars($pref) [expr {$SttamodeVars($pref) ? 0 : 1}]
- set oldMode $mode
- set mode "Stta"
- synchroniseModeVar $pref $SttamodeVars($pref)
- set mode $oldMode
- if {$SttamodeVars($pref)} {
- set end "on"
- } else {
- set end "off"
- }
- message "The \"$pref\" preference is now $end."
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Keyword Dictionaries ◊◊◊◊ #
- #
-
- # Making sure that SttaUserCommands and SttaUserOptions exist.
- # These will be over-ridden if they are loaded from a ${mode}Prefs.tcl file.
- #
-
- set SttaUserCommands ""
- set SttaUserOptions ""
-
- # ===========================================================================
- #
- # ◊◊◊◊ Stta Commands ◊◊◊◊ #
- #
- # this also includes a select few unix shell commands
- #
-
- set SttaCommands {
- STATA _qreg _robust accum acprplot adopath alpha anova aorder append
- areg assert auto.dta avplot avplots bcskew0 begin bitest bitesti blogit
- bmemsize boxcox bprobit brier bs bsample bsqreg bstat bstrap canon cc
- cchart cci cd centile cf ci cii clear clogit cmdtool cnreg cnsreg
- codebook coleq collapse colnames compare compress confirm constraint
- convert correlate count cox cprplot cross cs csi cumul cusum decode
- define degph delimit depnames describe dfbeta dictionary dir discard
- dispCns display do dprobit drop ds dydx echo egen eivreg else encode
- end erase ereg error existence exit expand factor fillin for format fsl
- function generate gladder global glogit glsaccum gnbreg gphdot gphpen
- gprobit graph greigen grmeanby groups gunzip gzip hadimvo heckman help
- hilite hold hotel if impute infile input inspect integ intreg ipolate
- iqreg ir iri kap kappa kapwgt keep ksm ksmirnov ktau kwallis ladder
- lfit linktest list lnskew0 local log logistic logit loneway lookfor
- lroc lrtest ls lstat ltable lv lvr2plot makeCns man matcproc maximize
- mcc mcci means memsize menu merge method mhodds mlogit mlout model move
- mvdecode mvencode mvreg mx_param nbreg nl nlinit nptrend ologit oprobit
- order outfile outsheet pause pchart pchi pcorr pd pd.X pd.ix pd.sunview
- pd.wy99 plot pnorm poisson post postclose postfile predict preserve
- probit profile.do pwcorr pwd qchi qnorm qqplot qreg quantile query
- range ranksum rchart recast recode regph regress rename renpfix replace
- report restore review rm rotate roweq rownames rreg run runtest rvfplot
- rvpplot sample save score sdtest sdtesti search serrbar sfrancia shell
- shewhart signrank signtest sktest smooth sort spearman sqreg stack stem
- substitute summarize sureg svd swilk symeigen symplot sysdir tab1 tab2
- tabi tabodds tabulate tempfile tempname tempvar testparm tobit touch
- ttest ttesti type uncompress unhold use vars vecaccum verinst version
- weibull which while window xchart xpose
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Prefixes ◊◊◊◊ #
-
- # This includes not only prefixes proper {capture, noisily, quietly}, but
- # also commands that are only part of command-phrases. These are
- # distinguished from SttaCommands for the Stta::Completions::Commands proc.
- #
-
- set SttaPrefixes {
- capture constraint eq estimates label macro matrix ml noisily program
- quietly reshape scalar set window xi:
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Parameters ◊◊◊◊ #
- #
-
- set SttaParameters {
- adosize ANSI beep contents graphics IBM level linesize matsize maxobs
- maxvar memory more obs output pagesize prefix rmsg seed textsize trace
- video virtual width
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Functions ◊◊◊◊ #
- #
-
- set SttaFunctions {
- abs atan autocode Binomial chiprob comma condcos diff exp float fprob
- gammap ge get group gt ibeta index int invbimonial invnorm invt iqr le
- length ln lngamma lower lt ltrim ma max mean median mod min norprob
- pctile rawsum real rank round rmean rmiss robs rtrim rsum sd sign sin
- sqrt string std substr sum thru tprob trim uniform upper
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Options ◊◊◊◊ #
- #
-
- set SttaOptions {
- .. Rescale V accumulate accuracy adjust all alt asif b1title b2title
- backward bands bar bartlett basecategory beta bin bonferroni border box
- bsize bwidth cell censored chi2 column connect constraints continuity
- cooksd corr covariance cutoff ddeviance dead delta density depname depv
- detail deviance df dof dx2 eform eps equal equation exact exposure
- factors failure fcnlabel fenter forward from fstay gamma gap genwt get
- group half hascons hat hazard histogram hlines horst hr i incr init
- initial intervals ipf irr iterate jitter l1title l2title leave lf0
- limits line lines lnlsq lnnormal lock lower lowess lrchi2 ltolerance
- margin mineigen missing mse1 noadjust noalt noanova noauto noaxis
- noborder nocoef nocone noconf nocons noconstant nodetail noformat
- nofreq nograph noheader nolabel nolog nomeans noobs norotate nostandard
- notab notable notest noties noweight number oneway or outcome pc pcd pe
- pen pie pr pr2 promax protect psize r1title r2title random rbox reps
- rescale resid residuals rlabel rlog root rrr rscale rstandard rstudent
- rtick rules scheffe select shading sidak split stabilzied star stdf
- stdp stdr strata symbol symbolic t1title t2title taub threshold title
- tlabel tolerance total tr trim ttick tune tvid twoway unequal unpaired
- upper varimax varp vlines vwidth wgt wide wlsiter wrap xb xlabel xlog
- xscale xtick ylabel ylog yscale ytick zero
- }
-
-
- # ===========================================================================
- #
- # ◊◊◊◊ Modifiers ◊◊◊◊ #
- #
-
- set SttaModifiers {
- .do .dot .dta .gph .help .log .pen .raw .xp TEMP _N _all _b _coef
- _merge _n _pi _rc _se aweight by fast frequency fweight in iweight
- ltolerance off old on pddefs pweight saving stata.do stata.hlp
- stata.lic stata.mnu stata.usr statpd title using value values variable
- variables weight
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Stata Macros ◊◊◊◊ #
- #
-
- set SttaMacros {
- S_ADO A_DATE S_E_ S_E_11 S_mdf S_nobs S_E_tdf S_FLAVOR S_FN
- S_MACHID S_mldbug S_MODE S_NOFKEY S_OS S_OSDTL S_TIME
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Dated Commands ◊◊◊◊ #
- #
-
- set SttaDated {
- _huber boot bootsamp chdir clogitp corc coxbase coxhaz coxvar datetof
- dbeta deff disp_res disp_s etodow etof etomdy fit fpredict ftodate ftoe
- ftomdy ftowdate genrank genstd genvmean glmpred grebar gwood hareg
- hereg hlogit hlu hprobit hreg huber kapmeier leverage logiodds
- logiodds2 loglogs logrank lpredict mantel mdytoe mdytof modify nlpred
- ologitp oprobitp parse regdw remap repeat stepwise survcurv survival
- survsum swcnreg swcox swereg swlogis swlogit swologit swoprbt swpois
- swprobit swqreg swtobit swweib textstd wdatetof wilcoxon xtpred
- }
-
- #==============================================================================#
- #
- # Colorize Stta
- #
- # Set all keyword lists, and colorize.
- #
- # Could also be called in a <mode>Prefs.tcl file
- #
-
- proc Stta::colorizeStta {{pref ""}} {
-
- global SttamodeVars SttaCommands SttaPrefixes SttaParameters
- global SttaFunctions SttaOptions SttaModifiers SttaMacros
- global SttaDated SttaUserCommands SttaUserOptions
-
- global SttaCommandList SttaOptionList Sttacmds
-
- # First setting aside only the commands, for Stta::Completion::Command.
- set SttaCommandList [concat \
- $SttaCommands $SttaPrefixes $SttamodeVars(addCommands) \
- $SttaUserCommands $SttaParameters \
- ]
-
- # Then setting aside only the options, for Sttaelectric().
- set SttaOptionList [concat \
- $SttaOptions $SttamodeVars(addOptions) $SttaUserOptions \
- ]
-
- # Then, create the list of all keywords for completions.
- set Sttacmds [lsort [concat \
- $SttaCommandList $SttaOptionList $SttaFunctions \
- $SttaModifiers $SttaDated \
- ]]
-
- # Commands, Prefixes, Parameters, User Macros
- regModeKeywords -a \
- -k $SttamodeVars(commandColor) Stta $SttaCommandList
-
- # Functions, Options, Modifiers, Stata-Macros,
- regModeKeywords -a \
- -k $SttamodeVars(optionColor) Stta \
- [concat $SttaOptionList $SttaFunctions \
- $SttaParameters $SttaModifiers $SttaMacros ]
-
- # Dated
- regModeKeywords -a \
- -k red Stta $SttaDated
-
- # Symbols
- regModeKeywords -a \
- -k $SttamodeVars(symbolColor) Stta {|} \
- -i "+" -i "-" -i "_" -i "\\" \
- -I $SttamodeVars(symbolColor)
-
- if {$pref != ""} {refresh}
- }
-
- # Call this now.
-
- Stta::colorizeStta
-
- # ===========================================================================
- #
- # Reload Completions.
- #
- # This is now an obsolete proc.
- #
-
- proc Stta::reloadCompletions {} {
- alertnote "\"Stta::reloadCompletions\" is an obsolete proc.\
- It should be removed from your SttaPrefs.tcl file."
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Key Bindings, Electrics ◊◊◊◊ #
- #
- # abbreviations: <o> = option, <z> = control, <s> = shift, <c> = command
- #
-
- # Known bug: Key-bindings from other global menus might conflict with those
- # defined in the Stata menu. This will help ensure that this doesn't happen.
-
- Bind 's' <cs> {Stta::switchToStata} Stta
- Bind 'd' <cs> {Stta::doFile} Stta
- Bind 'd' <csz> {Stta::doSelection} Stta
- Bind 'p' <cs> {Stta::insertPath} Stta
- Bind 'p' <csz> {Stta::programTamplate} Stta
-
- Bind '\;' <sz> {Stta::helpProc stataHelp semiDelimiter} Stta
- Bind ':' <sz> {Stta::helpProc stataHelp semiDelimiter} Stta
-
- Bind 'n' <sz> {Stta::nextCommand} Stta
- Bind 'p' <sz> {Stta::prevCommand} Stta
- Bind 's' <sz> {Stta::selectCommand} Stta
- Bind 'c' <sz> {Stta::copyCommand} Stta
-
- Bind 'i' <cz> {Stta::reformatCommand} Stta
-
- Bind '\r' <s> {Stta::continueCommand} Stta
- Bind '\)' {Stta::electricRight "\)"} Stta
-
- # For those that would rather use arrow keys to navigate. Up and down
- # arrow keys will advance to next/prev command, right and left will also
- # set the cursor to the top of the window.
-
- Bind up <sz> {Stta::prevCommand 0 0} Stta
- Bind left <sz> {Stta::prevCommand 0 1} Stta
- Bind down <sz> {Stta::nextCommand 0 0} Stta
- Bind right <sz> {Stta::nextCommand 0 1} Stta
-
- # ===========================================================================
- #
- # Stta Carriage Return
- #
- # Inserts a carriage return, and indents properly.
- #
-
- proc Stta::carriageReturn {} {
-
- global SttamodeVars
-
- if {[isSelection]} {deleteSelection}
-
- set pos1 [lineStart [getPos]]
- set pos2 [getPos]
- if {[regexp {^([\t ])*(end|\}|\))} [getText $pos1 $pos2]]} {
- createTMark temp $pos2
- catch {bind::IndentLine}
- gotoTMark temp ; removeTMark temp
- }
- insertText "\r"
- catch {bind::IndentLine}
- }
-
- # ===========================================================================
- #
- # Stta Electric Semi
- #
- # Inserts a semi, carriage return, and indents properly.
- #
-
- proc Stta::electricSemi {} {
-
- global SttamodeVars
-
- if {[isSelection]} {
- deleteSelection
- }
- if {[literalChar] || !$SttamodeVars(semiDelimiter)} {
- typeText {;}
- return
- }
- set pos1 [lineStart [getPos]]
- set pos2 [getPos]
- insertText {;}
- bind::CarriageReturn
- }
-
- # ===========================================================================
- #
- # Stta Electric Left, Right
- #
- # Adapted from "tclMode.tcl"
- #
-
- proc Stta::electricLeft {} {
-
- if {[literalChar]} {
- typeText "\{"
- return
- }
- set pat "\}\[ \t\r\n\]*(else(if)?)\[ \t\r\n\]*\$"
- set pos [getPos]
- if { [set result [findPatJustBefore "\}" $pat $pos word]] == "" } {
- insertText "\{"
- return
- }
- # we have an if/else(if)/else
- switch -- $word {
- "else" {
- deleteText [lindex $result 0] $pos
- elec::Insertion "\} $word \{\r\t••\r\}\r••"
- }
- "elseif" {
- deleteText [lindex $result 0] $pos
- elec::Insertion "\} $word \{••\} \{\r\t••\r\}\r••"
- }
- }
- }
-
- proc Stta::electricRight {{char "\}"}} {
-
- if {[literalChar]} {
- typeText $char
- return
- }
- set pos [getPos]
- typeText $char
- if {![regexp {[^ \t]} [getText [lineStart $pos] $pos]]} {
- set pos [lineStart $pos]
- createTMark temp [getPos]
- catch {bind::IndentLine}
- gotoTMark temp ; removeTMark temp
- bind::CarriageReturn
- }
- if {[catch {blink [matchIt $char [pos::math $pos - 1]]}]} {
- beep ; message "No matching $char !!"
- }
- }
-
- # ===========================================================================
- #
- # Continue Command
- #
- # Indenting continuation lines relative to start of command.
- #
-
- proc Stta::continueCommand {} {
-
- set thisLine [lindex [Stta::getCommandLine [lineStart [getPos]] 1 0] 2]
- set thisLine [string trim $thisLine]
- if {![regexp {/\*([^\*]*)$} $thisLine]} {
- typeText " /*"
- }
- Stta::carriageReturn
- insertText "*/ "
- }
-
- # This was the old proc, which didn't have Stta::indentLine available.
- #
- # Indenting continuation lines by one space relative to start of command.
- # (Note: Inserting space at first was the only way I was able to get this
- # to work when at the end of the last line of a file. -- lps)
-
- # proc Stta::continueCommand {} {
- # insertText " "
- # backwardChar
- # set begHere [search -s -f 0 -r 1 -i 0 {^[ \t]*[^ (\*\/)\t\r\n]} [getPos]]
- # set indAmt [getText [lindex $begHere 0] [pos::math [lindex $begHere 1] -1]]
- # insertText " /*\r$indAmt */"
- # forwardChar
- # }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Indentation ◊◊◊◊ #
- #
- # Stta::correctIndentation is necessary for Smart Paste, and returns the
- # correct level of indentation for the current line. Stta::indentLine uses
- # this level to indent the current line.
- #
- # We have three levels of indentation in Stata. The first is for the
- # continuation of commands, in which case we simply indent respecting the
- # Stta mode variable fullIndent. The second is for programs, in which case
- # we indent the start of each command by indentationAmount until we reach
- # an "end" command. The third is for nested {} statements.
- #
- # In Stta::correctIndentation, we grab the previous line, remove all of the
- # characters besides braces and quotes, and then convert it all to a list
- # to be evaluated. Braces contained within quotes, as well as literal
- # characters, should all be ignored and the remaining braces are used to
- # determine the correct level of nesting.
- #
- # This works really well for "simple" syntax files, without multi-line
- # block commented sections embedded in either program definitions or actual
- # commands.
- #
- # Known limitation (or a feature, depending on your point of view):
- # Indented lines of block comments will be recognized as "valid"
- # commands that are being continued, and themselves indented when a region
- # is formatted, leading to a construction that looks like this:
- #
- # command var
- #
- # /*
- # * It is important to note that the CPS files produced
- # * by the Census Bureau do not have decimal points in
- # * the data.
- # */
- #
- # next command var
- #
- # or maybe
- #
- # command var
- #
- # /* It is left to the documentation to inform
- # the user how many decimals are implied. The user
- # must make the proper adjustment before using
- # weights. This is true for all the weights.
- # */
- #
- # In this case, it's important that the ending */ appear on a line by
- # itself to signal that this line was a "continued" command, now complete.
- # It all gets messier when trying to figure out what a syntax file "should"
- # look like given the semi delimiter possibility, too ...
- #
-
- proc Stta::indentLine {{pos ""}} {
-
- if {$pos == ""} {set pos [getPos]}
- # Get details of current line.
- set posBeg [lineStart [getPos]]
- set text [getText $posBeg [nextLineStart $posBeg]]
- regexp {^[ \t]*} $text white
- set posNext1 [pos::math $posBeg + [string length $white]]
- set posNext2 [pos::math $posNext1 + 1]
- if {[pos::compare $posNext2 > [maxPos]]} {
- set posNext2 [maxPos]
- }
- # Determine the correct level of indentation for this line, given the
- # next character.
- set lwhite [Stta::correctIndentation $pos [getText $posNext1 $posNext2]]
- set lwhite [text::indentOf $lwhite]
- if {$white != $lwhite} {
- replaceText $posBeg $posNext1 $lwhite
- }
- goto [pos::math $posBeg + [string length $lwhite]]
- }
-
- proc Stta::correctIndentation {pos {next ""}} {
-
- global mode indent_amounts SttamodeVars
-
- if {$mode == "Stta"} {
- set continueIndent [expr {$SttamodeVars(fullIndent) + 1}]
- } else {
- set continueIndent 2
- }
-
- set posBeg [lineStart $pos]
- # Get information about this line, previous line ...
- set thisLine [Stta::getCommandLine $posBeg 1 2]
- set prevLine1 [Stta::getCommandLine [pos::math $posBeg - 1] 0 2]
- set prevLine2 [Stta::getCommandLine [pos::math [lindex $prevLine1 0] - 1] 0 2]
- set lwhite [lindex $prevLine1 1]
- # If we have a previous line ...
- if {[pos::compare [lindex $prevLine1 0] != $posBeg]} {
- set pL1 [string trim [lindex $prevLine1 2]]
- # Indent if the preceding command was a program definition.
- if {[regexp {^[\t ]*program+[\t ]+define} $pL1]} {
- incr lwhite $indent_amounts(2)
- }
- # Indent if the last line did not terminate the command.
- if {![Stta::endOfCommand $pL1]} {
- incr lwhite $indent_amounts($continueIndent)
- }
- # Check to make sure that the previous command was not itself a
- # continuation of the line before it.
- if {[pos::compare [lindex $prevLine1 0] != [lindex $prevLine2 0]]} {
- set pL2 [string trim [lindex $prevLine2 2]]
- if {![Stta::endOfCommand $pL2]} {
- incr lwhite $indent_amounts(-$continueIndent)
- }
- }
- # Find out if there are any unbalanced {,},(,) in the last line.
- regsub -all {[^ \{\}\(\)\"\*\/\\]} $pL1 { } line
- # Remove all literals.
- regsub -all {\\\{|\\\}|\\\(|\\\)|\\\"|\\\*|\\\/} $line { } line
- regsub -all {\\} $line { } line
- # Remove everything surrounded by quotes.
- regsub -all {\"([^\"]+)\"} $line { } line
- regsub -all {\"} $line { } line
- # Remove everything surrounded by bracketed comments.
- regsub -all {/\*([^\*/]+)\*/} $line { } line
- # Now turn all braces into 2's and -2's
- regsub -all {\{|\(} $line { 2 } line
- regsub -all {\}|\)} $line { -2 } line
- # This list should now only contain 2's and -2's.
- foreach i $line {
- if {$i == "2" || $i == "-2"} {incr lwhite $indent_amounts($i)}
- }
- # Did the last line start with a lone \) or \} ? If so, we want to
- # keep the indent, and not make call it an unbalanced line.
- if {[regexp {^[\t ]*(\}|\))} $pL1]} {
- incr lwhite $indent_amounts(2)
- }
- }
- # If we have a current line ...
- if {[pos::compare [lindex $thisLine 0] == $posBeg]} {
- # Reduce the indent if the first non-whitespace character of this
- # line is ) or \}, or an "end" command.
- set tL [lindex $thisLine 2]
- if {$next == "\}" || $next == ")" || [regexp {^[\t ]*(\}|\)|end)} $tL]} {
- incr lwhite $indent_amounts(-2)
- }
- }
- # Now we return the level to the calling proc.
- return [expr {$lwhite > 0 ? $lwhite : 0}]
- }
-
- # ===========================================================================
- #
- # Get Command Line
- #
- # Find the next/prev command line relative to a given position, and return
- # the position in which it starts, its indentation, and the complete text
- # of the command line. If the search for the next/prev command fails,
- # return an indentation level of 0.
- #
- # Unlike SPSS and SAS modes, we don't have the luxury of ignoring commented
- # lines since they could simply indicate the continuation of commands.
- #
-
- proc Stta::getCommandLine {pos {direction 1} {ignoreComments 1}} {
-
- if {$ignoreComments == 1} {
- set pat {^[\t ]*[^\t\r\n\*/ ]}
- } elseif {$ignoreComments == 2} {
- set pat {^[\t ]*[^\t\r\n/ ]}
- } else {
- set pat {^[\t ]*[^\t\r\n ]}
- }
- set posBeg [pos::math [lineStart $pos] - 1]
- if {[pos::compare $posBeg < [minPos]]} {
- set posBeg [minPos]
- }
- set lwhite 0
- if {![catch {search -f $direction -r 1 $pat $pos} match]} {
- set posBeg [lindex $match 0]
- set lwhite [posX [pos::math [lindex $match 1] - 1]]
- }
- set posEnd [pos::math [nextLineStart $posBeg] - 1]
- if {[pos::compare $posEnd > [maxPos]]} {
- set posEnd [maxPos]
- }
- return [list $posBeg $lwhite [getText $posBeg $posEnd]]
- }
-
- # ===========================================================================
- #
- # End of Command
- #
- # Determine if the command in a line of a given position was terminated.
- #
-
- proc Stta::endOfCommand {line} {
-
- global SttamodeVars
-
- if {!$SttamodeVars(semiDelimiter)} {
- # Check to see if the last line ended with /*, indicating continuation.
- if {[regexp {/\*([^\*]*)$} $line]} {
- return 0
- } else {
- return 1
- }
- } else {
- # Check to see if the last line ended with ;, indicating termination.
- if {[regexp {;([\t ]?)$} $line]} {
- return 1
- } else {
- return 0
- }
- }
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Command Double Click ◊◊◊◊ #
- #
- # First checks to see if this is a macro defined in current window.
- #
- # Then checks to see if the highlighted word appears in any keyword list,
- # and if so, sends the selected word to the www.stata.com help site. Stata
- # commands are case-sensitive, and so is the help search engine.
- #
- # Control-Command double click will insert syntax information in status bar.
- # Shift-Command double click will insert commented syntax information in window.
- # Option-Command double click will send the command to Stata application. (lps)
- #
- # If "Local Help" is checked, option vs not is reversed, so that command
- # double-click will send to local Stata application.
- #
-
- proc Stta::DblClick {from to shift option control} {
-
- global SttamodeVars SttaCommands SttaPrefixes SttaParameters SttaFunctions
- global SttaModifiers SttaMacros SttaDated SttaSyntaxMessage
-
- set validCommands [concat \
- $SttaCommands $SttaPrefixes $SttaParameters $SttaFunctions \
- $SttaModifiers $SttaMacros $SttaDated \
- ]
-
- select $from $to
- set command [getSelect]
- set macroDef {program[\t ]define[\t ]*$command[\t\r\n; ]}
-
- if {![catch {search -f 1 -r 1 $macroDef [minPos]} match]} {
- # First check current file for macro definition, and if found ...
- placeBookmark
- goto [lineStart [lindex $match 0]]
- message "press <Ctl .> to return to original cursor position"
- return
- # Could next check any open windows, or files in the current
- # window's folder ... but not implemented. For now, macros need
- # to be defined in current file.
- } elseif {[lsearch -exact $validCommands $command] == "-1"} {
- # If not a defined macro, check to see if it's a defined keyword.
- message "\"$command\" is not defined as a Stata system keyword."
- return
- }
- # Any modifiers pressed?
- if {$control} {
- # CONTROL -- Just put syntax message in status bar window
- if {[info exists SttaSyntaxMessage($command)]} {
- message $SttaSyntaxMessage($command)
- } else {
- message "Sorry, no syntax information available for $command"
- }
- } elseif {$shift} {
- # SHIFT --Just insert syntax message as commented text
- if {[lsearch -exact $SttaDated $command] != "-1"} {
- message "$SttaSyntaxMessage($command)"
- } elseif {[info exists SttaSyntaxMessage($command)]} {
- endOfLine
- insertText "\r"
- insertText "$SttaSyntaxMessage($command)"
- comment::Line
- } else {
- message "Sorry, no syntax information available for $command"
- }
- } elseif {$option && !$SttamodeVars(localHelp)} {
- # Now we have four possibilities, based on "option" key and the
- # preference for "local Help".
- #
- # OPTION, local help isn't checked -- Send command to local application
- Stta::localCommandHelp $command
- } elseif {$option && $SttamodeVars(localHelp)} {
- # OPTION, but local help is checked -- Send command for on-line help.
- Stta::wwwCommandHelp $command
- } elseif {$SttamodeVars(localHelp)} {
- # No modifiers, local help is checked -- Send command to local app.
- Stta::localCommandHelp $command
- } else {
- # No modifiers, no local help checked -- Send command for on-line
- # help. This is the "default" behavior.
- Stta::wwwCommandHelp $command
- }
- }
-
- # ===========================================================================
- #
- # WWW Command Help
- #
- # Send command to defined url, prompting for text if necessary.
- #
-
- proc Stta::wwwCommandHelp {{command ""}} {
-
- global SttamodeVars
-
- if {$command == ""} {
- set command [prompt "on-line help for ... " [getSelect]]
- # set command [statusPrompt "on-line help for ... " ]
- }
- message "\"$command\" sent to $SttamodeVars(helpUrl)"
- url::execute $SttamodeVars(helpUrl)$command
- }
-
- # ===========================================================================
- #
- # Local Command Help
- #
- # Send command to local application, prompting for text if necessary.
- #
- # -- lps
- #
- # Supposedly, this works on all platforms ... -- cbu
- #
-
- proc Stta::localCommandHelp {{command ""}} {
-
- if {$command == ""} {
- set command [prompt "local Stata application help for ... " [getSelect]]
- # set command [statusPrompt "local Stata application help for ... " ]
- }
- Stta::doSelection "whelp $command"
- }
-
- # ===========================================================================
- #
- # Command Help
- #
- # Send the command to a local Stata application if it exists, otherwise
- # send it the defined web site. (Used in the "Statistical Modes Help"
- # file, could easily be used in the menu if desired ...)
- #
-
- proc Stta::commandHelp {{command ""}} {
-
- global SttamodeVars tcl_platform
-
- if {$command == ""} {
- set command [prompt "Stata help for ..." ""]
- }
- if {[set command [string trim $command]] == ""} {
- message "Cancelled -- no command was entered."
- error "No command was entered."
- }
- if {[regexp $command " "]} {
- message "Cancelled -- only enter one command for help."
- error "Multiple commands requested."
- }
- set pf $tcl_platform(platform)
- set local 0
- if {$pf == "macintosh" && ![catch {nameFromAppl $SttamodeVars(stataSig)}]} {
- set local 1
- } elseif {($pf == "windows" && [file exists $SttamodeVars(stataSig)]} {
- set local 1
- } elseif {($pf == "unix" && [file exists $SttamodeVars(stataSig)]} {
- set local 1
- }
- if {$local} {
- Stta::localCommandHelp $command
- } else {
- Stta::wwwCommandHelp $command
- }
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Mark File and Parse Functions ◊◊◊◊ #
- #
-
- # ===========================================================================
- #
- # Stta Mark File
- #
- # This will return the first 35 characters from the first non-commented
- # word appearing in column 0. Codebook files will be marked differently,
- # listing variable names. All other output files (those not recognized)
- # will take into account the additional left margin elements added by
- # Stata.
- #
-
- proc Stta::MarkFile {{type ""}} {
-
- removeAllMarks
-
- message "Marking File …"
-
- set pos [minPos]
- set count 0
- # Figure out what type of file this is -- source, codebook, or output.
- # The variable "type" refers to a call from the Stata menu.
- # Otherwise we try to figure out the type based on the file's suffix.
- if {$type == ""} {
- if {[win::CurrentTail] == "* Stta Mode Example *"} {
- # Special case for Mode Examples, but only if called from
- # Marks menu. (Called from Stata menu, "type" will over-ride.
- set type ".do"
- } else {
- set type [file extension [win::CurrentTail]]
- }
- }
- # Now set the mark regexp.
- if {$type == ".do" || $type == ".ado" } {
- # Source file.
- set markExpr {^(!+[\t ]|\*\*\*[ ]|\*\*\*\*[ ])?[a-zA-Z0-9_\#]}
- } elseif {$type == ".codebook"} {
- # Codebook file, called from the Stata menu
- set markExpr {^[a-zA-Z0-9]+( \-)}
- } else {
- # None of the above, so assume that it's output
- set markExpr {^(\. )+((!+[\t ]|\*\*\*[ ]|\*\*\*\*[ ])?[a-zA-Z0-9_\#])}
- }
- # Mark the file
- while {![catch {search -f 1 -r 1 -m 0 -i 1 $markExpr $pos} match]} {
- incr count
- set posBeg [lindex $match 0]
- set posEnd [nextLineStart $posBeg]
- if {[pos::compare $posEnd > [maxPos]]} {set posEnd [maxPos]}
- set line [string trimright [getText $posBeg $posEnd]]
- # Get rid of the leading ". " for output files
- set line [string trimleft $line ". "]
- # Get rid of braces.
- regsub -all {\{|\[} $line {(} line
- regsub -all {\}|\]} $line {)} line
- # Add a little indentation so that section marks show up better.
- set line " $line"
- if {[regsub { \*\*\*\* } $line {* } line]} {
- incr count -1
- } elseif {[regsub { \*\*\* } $line {• } line]} {
- incr count -1
- }
- if {[string length $line] > 35} {
- set line "[string range $line 0 35] …"
- } else {
- # Get rid of trailing sem-colons.
- set line [string trimright $line ";" ]
- }
- if {$type == ".codebook"} {
- # Get rid of the trailing "-" for frequency / codebook files.
- regsub {[-]+( …)} $line { } line
- set line [string trimleft $line " "]
- message "# of variables: $count"
- }
- setNamedMark $line $posBeg $posBeg $posBeg
- set pos $posEnd
- }
- # Sorting the marks if this is a codebook.
- # (Code lifted from "sortMarksFile", in "marks.tcl")
- if {$type == ".codebook"} {
- message "Sorting marks …"
- set mks {}
- foreach mk [getNamedMarks] {
- removeNamedMark -n [lindex $mk 0] -w [lindex $mk 1]
- lappend mks $mk
- }
- foreach mk [lsort $mks] {
- set name [lindex $mk 0]
- set disp [lindex $mk 2]
- set pos [lindex $mk 3]
- set end [lindex $mk 4]
-
- setNamedMark $name $disp $pos $end
- }
- message "This codebook describes $count variables."
- } else {
- message "This file contains $count commands."
- }
- }
-
- # ===========================================================================
- #
- # Stta Parse Functions
- #
- # This will return only the Stta command names. All other output files
- # (those not recognized) will take into account the additional left margin
- # elements added by Stata.
- #
-
- proc Stta::parseFuncs {} {
-
- global sortFuncsMenu
-
- set ext [file extension [win::CurrentTail]]
-
- # Determine the file type.
- if {$ext == ".do" || $ext == ".ado"} {
- set funcExpr {^(\w+)}
- } elseif {[file tail [win::Current]] == "* Stta Mode Example *"} {
- # Special case for Mode Examples folder
- set funcExpr {^(\w+)}
- } else {
- # We don't worry about codebooks here, we'll just parse as output.
- set funcExpr {^(\. )(\w+)}
- }
- # Parse the file.
- set pos [minPos]
- set m {}
- while {[set match [search -f 1 -r 1 -i 0 -n $funcExpr $pos]] != ""} {
- if {[regexp -- {(\w+)} [eval getText $match] "" word]} {
- lappend m [list $word [lindex $match 0]]
- }
- set pos [lindex $match 1]
- }
- # Sort the functions if necessary, but regsub either way.
- if {$sortFuncsMenu} {
- regsub -all "\[\{\}\]" [lsort -ignore $m] "" m
- } else {
- regsub -all "\[\{\}\]" $m "" m
- }
- return $m
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ -------------------- ◊◊◊◊ #
- #
- # ◊◊◊◊ Stata Menu ◊◊◊◊ #
- #
- # version: 1.2
- #
- # Author: L. Phillip Schumm
- # E-mail: <pschumm@uchicago.edu>
- #
- # If Stata is launched from Alpha, then Stata's own directory will become
- # the working directory unless a profile.do file is used to change it.
- #
- # version history:
- #
- # 1.1 lps Contributed menu to stataMode.tcl
- # 1.2 cbu Added "Mark File As", simplified Stta::menuProc .
- # Added "Help", added optional argument to doFile .
- # Changed "Menu -n ..." proc to "menu::buildProc stataMenu ...".
- # 1.3 cbu Added more preferences to Help section, and Navigation section.
- # 2.0 cbu Updated for Alpha 7.4, added "Stata Home Page" menu item.
- # 2.1 cbu Added "Keywords" submenu, cleaning up "Help"
- #
-
- # This was the old menu definition proc.
-
- # Menu -n $stataMenu -p Stta::menuProc -M Stta {
- # "/S<U<OswitchToStata"
- # "(-"
- # "/D<U<OdoFile"
- # "/D<U<O<BdoSelection"
- # {Menu -n markStataFileAs -p Stta::markFileProc {
- # "source"
- # "output"
- # "codebook" }
- # }
- # {Menu -n StataHelp -p Stta::helpProc {
- # "/t<BstataModeHelp"
- # "/t<IlocalCommandHelp…"
- # "/t<OwwwCommandHelp…" }
- # }
- # "(-"
- # "/P<U<OinsertPath"
- # "/P<U<O<BprogramTemplate"
- # }
-
- # Tell Alpha what procedures to use to build all menus, submenus.
-
- menu::buildProc stataMenu Stta::buildMenu
- menu::buildProc stataHelp Stta::buildHelpMenu
- menu::buildProc stataKeywords Stta::buildKeywordsMenu
- menu::buildProc markStataFileAs… Stta::buildMarkMenu
-
- # First build the main Stata menu.
-
- proc Stta::buildMenu {} {
-
- global stataMenu
-
- set menuList [list \
- "stataHomePage" \
- "/S<U<OswitchToStata" \
- [list Menu -n stataHelp -M Stta {}] \
- "(-" \
- [list Menu -n stataKeywords -M Stta {}] \
- [list Menu -n markStataFileAs… -M Stta {}] \
- "(-" \
- "/D<U<OdoFile" \
- "/D<U<O<BdoSelection" \
- "(-" \
- "/P<U<OinsertPath" \
- "/P<U<O<BprogramTemplate" \
- "/b<UcontinueCommand" \
- "(-" \
- "/N<U<BnextCommand" \
- "/P<U<BprevCommand" \
- "/S<U<BselectCommand" \
- "/I<B<OreformatCommand" \
- ]
- set submenus [list stataHelp stataKeywords markStataFileAs… ]
- return [list build $menuList Stta::menuProc $submenus $stataMenu]
- }
-
- # Then build the "Stata Help" submenu.
-
- proc Stta::buildHelpMenu {} {
-
- global SttamodeVars SttaPrefsInMenu alpha::platform
-
- # Determine which key should be used for "Help", with F8 as option.
-
- if {!$SttamodeVars(noHelpKey)} {
- set key "/t"
- } else {
- set key "/l"
- }
-
- # Reverse the local, www key bindings depending on the value of the
- # 'Local Help" variable.
-
- if {!$SttamodeVars(localHelp)} {
- set menuList [list \
- "${key}<OwwwCommandHelp…" \
- "${key}<IlocalCommandHelp…" \
- ]
- } else {
- set menuList [list \
- "${key}<OlocalCommandHelp…" \
- "${key}<IwwwCommandHelp…" \
- ]
- }
- lappend menuList "(-"
- if {${alpha::platform} == "alpha"} {
- set prefix "!√"
- } else {
- set prefix "!•"
- }
- foreach pref $SttaPrefsInMenu {
- if {$SttamodeVars($pref)} {
- if {$pref == "semiDelimiter"} {set pref "/;<U<B$pref"}
- lappend menuList "${prefix}$pref"
- } else {
- if {$pref == "semiDelimiter"} {set pref "/;<U<B$pref"}
- lappend menuList "$pref"
- }
- }
- lappend menuList "(-"
- lappend menuList "setStataApplication"
- lappend menuList "(-"
- lappend menuList "${key}<BstataModeHelp"
-
- return [list build $menuList Stta::helpProc {}]
- }
-
- # Then build the "Stta Mode Keywords" submenu.
-
- proc Stta::buildKeywordsMenu {} {
-
- set menuList [list \
- "listKeywords" \
- "checkKeywords" \
- "addNewCommands" \
- "addNewOptions" \
- ]
- return [list build $menuList Stta::keywordsProc {}]
- }
-
- # Then build the "Mark Stata File As" submenu.
-
- proc Stta::buildMarkMenu {} {
-
- global SttamodeVars alpha::platform
-
- set menuList [list \
- "source" \
- "output" \
- "codebook" \
- "(-" \
- ]
- if {${alpha::platform} == "alpha"} {
- set prefix "!√"
- } else {
- set prefix "!•"
- }
- if {$SttamodeVars(autoMark)} {
- lappend menuList "${prefix}autoMark"
- } else {
- lappend menuList "autoMark"
- }
-
- return [list build $menuList Stta::markFileProc {}]
- }
-
-
- proc Stta::rebuildMenu {{menuName "stataMenu"} {pref ""}} {
- menu::buildSome $menuName
- }
-
- # Dim some menu items when there are no open windows.
- set menuItems {
- markStataFileAs… doFile doSelection
- insertPath programTamplate continueCommand
- nextCommand prevCommand selectCommand reformatCommand
- }
- foreach i $menuItems {
- hook::register requireOpenWindowsHook [list stataMenu $i] 1
- }
- unset i menuItems
-
- # Now we actually build the Stata menu.
-
- menu::buildSome stataMenu
-
- # ===========================================================================
- #
- # ◊◊◊◊ Stata menu support ◊◊◊◊ #
- #
-
- # This is the procedure called for all main menu items.
-
- proc Stta::menuProc {menuName item} {Stta::$item}
-
- # Give a beta message for untested features / menu items.
-
- proc Stta::betaMessage {{kill 1}} {
-
- message "Sorry,this feature has not been fully implemented."
- if {$kill} {return -code return}
- }
-
- # ===========================================================================
- #
- # Open the Stata home page.
- #
-
- proc Stta::stataHomePage {} {
-
- global SttamodeVars
-
- url::execute $SttamodeVars(stataHomePage)
- }
-
- # ===========================================================================
- #
- # Switch to Stata application.
- #
-
- proc Stta::switchToStata {} {app::launchFore [Stta::sig]}
-
- # ===========================================================================
- #
- # Return the Stata signature.
- #
-
- proc Stta::sig {{app "Stata"}} {
-
- global SttamodeVars tcl_platform
-
- set lowApp [string tolower $app]
- set capApp [string toupper $app]
- set pf $tcl_platform(platform)
-
- if {$pf == "macintosh"} {
- # Make sure that the Macintosh application for the signature exists.
- if {[catch {nameFromAppl $SttamodeVars(${lowApp}Sig)}]} {
- alertnote "Looking for the $capApp application ..."
- Stta::setApplication $lowApp
- }
- } elseif {$pf == "windows" || $pf == "unix"} {
- # Make sure that the Windows application for the signature exists.
- # We assume that this will work for unix, too.
- if {![file exists $SttamodeVars(${lowApp}Sig)]} {
- alertnote "Looking for the $capApp application ..."
- Stta::setApplication $lowApp
- }
- }
- return $SttamodeVars(${lowApp}Sig)
- }
-
- # ===========================================================================
- #
- # Set Application
- #
- # Prompt the user to locate the local Stata application.
- #
-
- proc Stta::setApplication {{app "Stata"}} {
-
- global mode SttamodeVars
-
- set lowApp [string tolower $app]
- set capApp [string toupper $app]
-
- set newSig ""
- set newSig [dialog::askFindApp $capApp $SttamodeVars(${lowApp}Sig)]
-
- if {$newSig != ""} {
- set SttamodeVars(${lowApp}Sig) "$newSig"
- set oldMode $mode
- set mode "Stta"
- synchroniseModeVar "${lowApp}Sig" $SttamodeVars(${lowApp}Sig)
- set mode $oldMode
- message "The $capApp signature has been changed to \"$newSig\"."
- } else {
- message "Cancelled."
- }
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Help ◊◊◊◊ #
- #
-
- proc Stta::helpProc {menuName item} {
-
- global SttamodeVars SttaPrefsInMenu
-
- if {$item == "wwwCommandHelp"} {
- Stta::wwwCommandHelp
- } elseif {$item == "localCommandHelp"} {
- Stta::localCommandHelp
- } elseif {[lsearch -exact $SttaPrefsInMenu $item] != -1} {
- Stta::flagFlip $item
- Stta::rebuildMenu stataHelp
- } elseif {$item == "setStataApplication"} {
- Stta::setApplication "Stata"
- } elseif {$item == "stataModeHelp"} {
- package::helpFile "Stta"
- } else {
- Stta::$item
- }
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Keywords ◊◊◊◊ #
- #
-
- proc Stta::keywordsProc {menuName item} {
-
- global Sttacmds
-
- if {$item == "listKeywords"} {
- set keywords [listpick -l -p "Current Stata mode keywords…" $Sttacmds]
- foreach keyword $keywords {
- Stta::checkKeywords $keyword
- }
- } elseif {$item == "addNewCommands" || $item == "addNewOptions"} {
- set item [string trimleft $item "addNew"]
- if {$item == "Commands" && [llength [winNames]] && [askyesno \
- "Would you like to add all of the \"extra\" commands from this window\
- to the \"Add Commands\" preference?"] == "yes"} {
- Stta::addWindowCommands
- } else {
- Stta::addKeywords $item
- }
- } else {
- Stta::$item
- }
- }
-
- # ===========================================================================
- #
- # Stta::addWindowCommands
- #
- # Add all of the "extra" commands which appear in entries in this window.
- #
-
- proc Stta::addWindowCommands {} {
-
- global mode Sttacmds SttamodeVars
-
- if {![llength [winNames]]} {
- message "Cancelled -- no current window!"
- return
- }
-
- message "Scanning [win::CurrentTail] for all commands…"
-
- set pos [minPos]
- set pat {^([a-zA-Z0-9]+[a-zA-Z0-9])+[\t ]}
- while {![catch {search -f 1 -r 1 $pat $pos} match]} {
- set pos [nextLineStart [lindex $match 1]]
- set commandLine [getText [lindex $match 0] [lindex $match 1]]
- regexp $pat $commandLine match aCommand
- if {![lcontains Sttacmds $aCommand]} {
- append SttamodeVars(addCommands) " $aCommand"
- }
- }
- set SttamodeVars(addCommands) [lsort [lunique $SttamodeVars(addCommands)]]
- set oldMode $mode
- set mode "Stta"
- synchroniseModeVar addCommands $SttamodeVars(addCommands)
- set mode $oldMode
- if {[llength $SttamodeVars(addCommands)]} {
- Stta::colorizeStta
- listpick -p "The \"Add Commands\" preference includes:" \
- $SttamodeVars(addCommands)
- message "Use the \"Mode Prefs --> Preferences\" menu item to edit keyword lists."
- } else {
- message "No \"extra\" commands from this window were found."
- }
- }
-
- # ===========================================================================
- #
- # Stta::addKeywords
- #
- # Prompt the user to add keywords for a given category.
- #
-
- proc Stta::addKeywords {{category} {keywords ""}} {
-
- global mode SttamodeVars
-
- if {$keywords == ""} {
- set keywords [prompt "Enter new Stata $category:" ""]
- }
-
- # Check to see if the keyword is already defined.
- foreach keyword $keywords {
- set checkStatus [Stta::checkKeywords $keyword 1 0]
- if {$checkStatus != 0} {
- alertnote "Sorry, \"$keyword\" is already defined\
- in the $checkStatus list."
- message "Cancelled."
- return -code return
- }
- }
- # Keywords are all new, so add them to the appropriate mode preference.
- append SttamodeVars(add$category) " $keywords"
- set SttamodeVars(add$category) [lsort $SttamodeVars(add$category)]
- set oldMode $mode
- set mode "Stta"
- synchroniseModeVar add$category $SttamodeVars(add$category)
- set mode $oldMode
- Stta::colorizeStta
- message "\"$keywords\" added to $category preference."
- }
-
- proc Stta::checkKeywords {{newKeywordList ""} {quietly 0} {noPrefs 0}} {
-
- global SttamodeVars
-
- global SttaCommands SttaUserCommands SttaPrefixes SttaParameters
- global SttaFunctions SttaOptions SttaUserOptions SttaModifiers
- global SttaMacros SttaDated
-
- set type 0
- if {$newKeywordList == ""} {
- set quietly 0
- set newKeywordList [prompt "Enter Stata mode keywords to be checked:" ""]
- }
- # Check to see if the new keyword(s) is already defined.
- foreach newKeyword $newKeywordList {
- if {[lsearch -exact $SttaCommands $newKeyword] != "-1"} {
- set type SttaCommands
- } elseif {[lsearch -exact $SttaUserCommands $newKeyword] != "-1"} {
- set type SttaUserCommands
- } elseif {[lsearch -exact $SttaPrefixes $newKeyword] != "-1"} {
- set type SttaPrefixes
- } elseif {[lsearch -exact $SttaParameters $newKeyword] != "-1"} {
- set type SttaParameters
- } elseif {[lsearch -exact $SttaFunctions $newKeyword] != "-1"} {
- set type SttaFunctions
- } elseif {[lsearch -exact $SttaOptions $newKeyword] != "-1"} {
- set type SttaOptions
- } elseif {[lsearch -exact $SttaUserOptions $newKeyword] != "-1"} {
- set type SttaUserOptions
- } elseif {[lsearch -exact $SttaModifiers $newKeyword] != "-1"} {
- set type SttaModifiers
- } elseif {[lsearch -exact $SttaMacros $newKeyword] != "-1"} {
- set type SttaMacros
- } elseif {[lsearch -exact $SttaDated $newKeyword] != "-1"} {
- set type SttaDated
- } elseif {!$noPrefs && \
- [lsearch -exact $SttamodeVars(addCommands) $newKeyword] != "-1"} {
- set type SttamodeVars(addCommands)
- } elseif {!$noPrefs && \
- [lsearch -exact $SttamodeVars(addOptions) $newKeyword] != "-1"} {
- set type SttamodeVars(addOptions)
- }
- if {$quietly} {
- # When this is called from other code, it should only contain
- # one keyword to be checked, and we'll return it's type.
- return "$type"
- } elseif {!$quietly && $type == 0} {
- alertnote "\"$newKeyword\" is not currently defined\
- as a Stta mode keyword."
- } elseif {$type != 0} {
- # This will work for any other value for "quietly", such as 2
- alertnote "\"$newKeyword\" is currently defined as a keyword\
- in the \"$type\" list."
- }
- set type 0
- }
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Marks ◊◊◊◊ #
- #
-
- proc Stta::markFileProc {menuName item} {
-
- if {$item == "source"} {
- Stta::MarkFile {.do}
- } elseif {$item == "output"} {
- # doesn't really matter what we put for the mark file "type" here,
- # since output is the default if other "if ..." cases aren't met.
- Stta::MarkFile {.out}
- } elseif {$item == "codebook"} {
- Stta::MarkFile {.codebook}
- } elseif {$item == "autoMark"} {
- Stta::flagFlip autoMark
- Stta::rebuildMenu markStataFileAs…
- }
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Processing ◊◊◊◊ #
- #
-
- # ===========================================================================
- #
- # Do FIle
- #
- # Send entire file to Stata for processing, adding carriage return at end
- # of file if necessary. Note that unlike Stata's do-file editor, the name
- # of the actual file appears in Stata's output window!
- #
- # Optional "f" argument allows this to be called by other code, or to be
- # sent via a Tcl shell window.
- #
-
- proc Stta::doFile {{f ""} {app "Stata"}} {
-
- if {$f != ""} {file::openAny $f}
- set f [win::Current]
-
- set dirtyWindow [winDirty]
- set dontSave 0
- if {$dirtyWindow && [askyesno \
- "Do you want to save the file before sending it to Stata?"] == "yes"} {
- save
- } else {
- set dontSave 1
- }
- if {!$dontSave && [lookAt [pos::math [maxPos] - 1]] != "\r"} {
- set pos [getPos]
- goto [maxPos]
- insertText "\r"
- goto $pos
- alertnote "Carriage return added to end of file."
- save
- }
-
- app::launchBack '[Stta::sig]'
- sendOpenEvent noReply '[Stta::sig]' $f
- switchTo '[Stta::sig]'
- }
-
- # ===========================================================================
- #
- # Do Selection
- #
- # Procedure to implement transfer of selected lines to Stata for processing.
- #
-
- proc Stta::doSelection {{selection ""} {app "Stata"}} {
-
- global PREFS
-
- if {$selection == ""} {
- if {![isSelection]} {
- message "No selection -- cancelled."
- return
- } else {
- set selection [getSelect]
- }
- }
- file::ensureDirExists [file join $PREFS Stata-tmp]
- set newFile [file join $PREFS Stata-tmp temp-Stata.do]
- file::writeAll $newFile $selection 1
-
- app::launchBack '[Stta::sig]'
- sendOpenEvent noReply '[Stta::sig]' $newFile
- switchTo '[Stta::sig]'
- }
-
- proc Stta::quitHook {} {temp::cleanup Stata-tmp}
-
- # ===========================================================================
- #
- # ◊◊◊◊ Insertions ◊◊◊◊ #
- #
-
- proc Stta::insertPath {} {
-
- global file::separator
-
- set path ""
- set t ""
- append t "\"${file::separator}"
- set path [getfile "Choose path of target file:"]
- if {$path != ""} {
- append t $path
- append t "\""
- typeText $t
- }
- }
-
- # An example of Stata specific electric insertion templates that could be
- # added to the menu.
-
- proc Stta::programTemplate {} {
-
- global SttamodeVars
-
- set end [lindex [Stta::getCommand [getPos]] 1]
- if {$end != "-1" && $end > [getPos]} {
- goto $end
- }
- if {$SttamodeVars(semiDelimiter)} {
- set eol " ;\r"
- } else {
- set eol "\r"
- }
-
- set pt "program define •progname•${eol}\tversion 6.0${eol}\tif \"`1'\""
- append pt " == \"?\" {\r\t\tglobal S_1 \"•variable names•\"${eol}\t\t"
- append pt "exit${eol}\t}${eol}\t••\r\t* (each result below must correspond"
- append pt " to a variable in S_1)${eol}\tpost `1' •results•${eol}end${eol}"
- elec::Insertion $pt
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ Navigation ◊◊◊◊ #
- #
-
- # Next/Prev command can simply return the position of the next command
- # (quietly == 1), move the cursor to the next command (placing the cursor
- # at the top of the window if toTop == 1), extend the current selection to
- # the end of the this command, or (if the current command is already
- # highlighted in its entirety) extend the current selection to the end of
- # the next command.
- #
-
- proc Stta::nextCommand {{quietly 0} {toTop 0}} {
-
- if {[pos::compare [selEnd] == [maxPos]]} {
- set pos [maxPos]
- } else {
- set pos [pos::math [selEnd] + 1]
- }
- set pat {^[^\r\n\t \*/]}
-
- if {![catch {search -f 1 -r 1 $pat $pos} match]} {
- set pos [lineStart [lindex $match 1]]
- } else {
- set pos [maxPos]
- }
- if {$quietly} {
- return $pos
- } elseif {[isSelection]} {
- set limit1 [lindex [Stta::getCommand [selEnd]] 1]
- set limit2 [lindex [Stta::getCommand $pos ] 1]
- if {$limit2 == "-1"} {set limit2 [maxPos]}
- if {$limit1 == "-1"} {set limit1 $limit2}
- if {[pos::compare [selEnd] < $limit1]} {
- select [getPos] $limit1
- } else {
- select [getPos] $limit2
- }
- } elseif {$pos == [maxPos]} {
- message "No further commands in the file."
- return
- } else {
- goto $pos
- message [getText $pos [nextLineStart $pos]]
- }
- if {$toTop} {insertToTop}
- }
-
- proc Stta::prevCommand {{quietly 0} {toTop 0}} {
-
- if {[pos::compare [getPos] == [minPos]]} {
- set pos [minPos]
- } else {
- set pos [pos::math [getPos] - 1]
- }
- set pat {^[^\r\n\t \*/]}
-
- if {![catch {search -f 0 -r 1 $pat $pos} match]} {
- set pos [lineStart [lindex $match 1]]
- } else {
- set pos [minPos]
- }
- if {$quietly} {
- return $pos
- } elseif {[isSelection]} {
- # Going backwards is actually easier with selections.
- select $pos [selEnd]
- } elseif {$pos == [minPos]} {
- message "No further commands in the file."
- return
- } else {
- goto $pos
- message [getText $pos [nextLineStart $pos]]
- }
- if {$toTop} {insertToTop}
- return $pos
- }
-
- proc Stta::searchFunc {direction} {
-
- if {$direction} {
- Stta::nextCommand
- } else {
- Stta::prevCommand
- }
- }
-
- proc Stta::selectCommand {} {
-
- set pos [getPos]
- set limits [Stta::getCommand $pos]
- set posBeg [lindex $limits 0]
- set posEnd [lindex $limits 1]
- set test1 [pos::compare $pos >= $posBeg]
- set test2 [pos::compare $pos <= $posEnd]
- if {$posBeg != "-1" && $test1 && $test2} {
- select $posBeg $posEnd
- } else {
- message "The cursor is not within a command."
- error "The cursor is not within a command."
- }
- }
-
- proc Stta::copyCommand {{quietly 0}} {
-
- set pos [getPos]
- if {[set posBeg [lindex [Stta::getCommand $pos] 0]] != "-1"} {
- goto $posBeg
- forwardWord
- set posEnd [getPos]
- if {!$quietly} {
- select $posBeg $posEnd
- copy
- message "\"[getText $posBeg $posEnd]\" copied to clipboard."
- }
- goto $pos
- return [getText $posBeg $posEnd]
- } elseif {!$quietly} {
- message "The cursor is not within a command."
- }
- return ""
- }
-
- proc Stta::reformatCommand {} {
-
- if {![isSelection]} {Stta::selectCommand}
- message "Reformatting …"
- ::indentRegion
- goto [pos::math [getPos] -1]
- goto [Stta::nextCommand 1]
- message "Reformatted."
- }
-
- proc Stta::getCommand {pos} {
-
- set pos1 [pos::math [nextLineStart $pos] - 1]
- set pat {^[^\r\n\t \}\)]}
- set posBeg "-1"
- set posEnd "-1"
- if {![catch {search -f 0 -r 1 $pat $pos1} match]} {
- set posBeg [lindex $match 0]
- set pos2 [nextLineStart $posBeg]
- if {![catch {search -f 1 -r 1 $pat $pos2} match]} {
- set posEnd [lindex $match 0]
- } else {
- set posEnd [maxPos]
- }
- # Now back up to remove empty or commented lines.
- set posEndPrev [pos::math $posEnd - 1]
- set prevLine [getText [lineStart $posEndPrev] $posEndPrev]
- while {[regexp {^[\t ]*$} $prevLine]} {
- set posEnd [lineStart $posEndPrev]
- set posEndPrev [pos::math $posEnd - 1]
- set prevLine [getText [lineStart $posEndPrev] $posEndPrev]
- }
- }
- return [list $posBeg $posEnd]
- }
-
- # ===========================================================================
- #
- # ◊◊◊◊ --------------------- ◊◊◊◊ #
- #
- # ◊◊◊◊ version history ◊◊◊◊ #
- #
- # modified by vers# reason
- # -------- --- ------ -----------
- # 01/28/20 cbu 1.0.1 First created Stata mode, based upon other modes found
- # in Alpha's distribution. Commands are based on
- # release version 3.1 of Stata.
- # 03/02/20 cbu 1.0.2 Minor modifications to comment handling.
- # 03/20/00 cbu 1.0.3 Minor update of keywords dictionaries.
- # Renamed mode Stta, from stta
- # 04/01/00 cbu 1.0.4 Added new preferences to allow the user to enter
- # additional commands and options.
- # Reduced the number of different user-specified colors.
- # Added "Stta::updateColors" to avoid need for a restart.
- # 04/08/00 cbu 1.0.5 Unset obsolete preferences from earlier versions.
- # Modified "Stta::electricSemi", added key-bindings for
- # "Continue Comment", and "Electric Return Over-ride".
- # Renamed "Stta::updateColors" to "Stta::updatePreferences".
- # 04/16/00 cbu 1.1 Renamed to stataMode.tcl
- # Added "Stta::MarkFile" and "Stta::parseFuncs".
- # Added command double-click for on-line help.
- # 06/20/00 cbu 1.2 "Mark File" now recognizes headings as well as commands.
- # "Mark File" recognizes source, output, or codebook files.
- # Completions, Completions Tutorial added.
- # "Reload Completions", referenced by "Update Preferences".
- # Better support for user defined keywords.
- # Removed "Continue Comment", now global in Alpha 7.4.
- # <shift, control>-<command> double-click syntax info.
- # lps <option>-<command> double-click Stata app .hlp help.
- # lps Added Phil Schumm's Stata Menu.
- # lps Added "Continue Command" key binding and proc.
- # Added "localHelpOnly" variable for command double-click.
- # 08/23/00 cbu 1.2.1 "Mark File As" added to Stata menu. (Required adding
- # an optional argument to Stta::MarkFile, reworking
- # of the stata menu build procs.)
- # "Help" added to Stata menu. (Required splitting off
- # "wwwCommandHelp" and "localCommandHelp" from
- # command double-click, giving them optional arguments.
- # Gave "doFile" an optional argument, so that it could
- # be called from other code, or a shell.
- # DblClick now looks for macro definitions in current file.
- # "localHelpOnly" preference changed to "localHelp"
- # Changing "localHelp" changes Stata Help menu bindings.
- # Small fixes to SttaCompletions.tcl.
- # Removed "codebookSuffix" preference, now that the
- # menu has "Mark File As…".
- # Added "stataSig" preference to allow user to find
- # local application if necessary.
- # Added "Stta::sig" which returns Stata signature.
- # 08/28/00 cbu 1.2.2 Added some of the flag preferences to "Stata Help" menu.
- # Added "Stta::flagFlip" to change bullets in menu.
- # Added a "noHelpKey" preference, which switches the
- # "help" key binding to F8.
- # Added "addNewCommands/Options" to "Stata Help" menu.
- # Added "setStataApplication to "Stata Help" menu.
- # 11/05/00 cbu 1.3 Added "next/prevCommand", "selectCommand", and
- # "copyCommand" procs to menu.
- # Added "continueComment" to menu.
- # Added "Stta::indentLine".
- # Added "reformatCommand" to menu.
- # Modified "Stta::continueCommand" to take advantage of
- # automatic indentation using Stta::indentLine.
- # Modified Stta::programTemplate to take semi delimiter
- # into account, and to not insert within a command.
- # "Stta::reloadCompletions" is now obsolete.
- # "Stta::updatePreferences" is now obsolete.
- # "Stta::colorizeStta" now takes care of setting all
- # keyword lists, including Sttacmds.
- # Cleaned up completion procs. This file never has to be
- # reloaded. (Similar cleaning up for "Stta::DblClick").
- # 11/16/00 cbu 2.0 New url prefs handling requires 7.4b21
- # Added "Home Page" pref, menu item.
- # Removed hook::register requireOpenWindowsHook from
- # mode declaration, put it after menu build.
- # 12/19/00 cbu 2.1 The menu proc "Add Commands" now includes an option
- # to grab all of the "extra" command from the current
- # window, using Stta::addWindowCommands.
- # Added "Keywords" submenu, "List Keywords" menu item.
- # Big cleanup of ::sig, ::setApplication, processing ...
- # 01/25/01 cbu 2.1.1 Bug fix for Stta::doSelection.
- # Bug fix for comment characters.
- # Better codebook marking.
- # Added Stta::commandHelp for help file hyperlinks.
- #
-
- # ===========================================================================
- #
- # .
-